﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Data;
using System.Diagnostics.Contracts;

namespace Numero3DBObject
{
    public class ConnexionDB : IDisposable
    {
        private const string CHAINE_CONNEXION = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=cours.mdb";
        private static ConnexionDB maConnexion;
        private OleDbConnection oleConnexion;
        private DataSet datasetConnexion;


        public static ConnexionDB MaConnexion
        {
            get { return ConnexionDB.maConnexion; }
            set { ConnexionDB.maConnexion = value; }
        }

        public OleDbConnection OleConnexion
        {
            get { return oleConnexion; }
            set { oleConnexion = value; }
        }


        public static ConnexionDB Creer()
        {
            Contract.Requires(!String.IsNullOrEmpty(CHAINE_CONNEXION), "La chaîne de connexion doit être définie.");
            Contract.Ensures(maConnexion.oleConnexion != null, "Erreur à la création de la connexion.");

            if (maConnexion == null)
            {
                maConnexion = new ConnexionDB();
                maConnexion.oleConnexion = new OleDbConnection(CHAINE_CONNEXION);
                maConnexion.datasetConnexion = new DataSet();
            }
            return maConnexion;
        }

        public static void Detruire()
        {
            Contract.Ensures(maConnexion == null, "Erreur à la destruction de la connexion.");

            if (maConnexion != null && maConnexion.oleConnexion.State == System.Data.ConnectionState.Closed)
            {
                maConnexion.Dispose();
                maConnexion = null;
            }
        }


        public List<Etudiant> ExecuterAdapterEtudiant(string commande, List<OleDbParameter> parametres = null)
        {
            Contract.Requires(MaConnexion.OleConnexion != null, "Erreur à l'ouverture de la connexion.");
            Contract.Requires(!String.IsNullOrEmpty(commande), "La commande doit être définie.");
            Contract.Ensures(MaConnexion.OleConnexion.State == ConnectionState.Closed,"La connexion ne c'est pas fermer correctement");

            
            List<Etudiant> listeRetour = new List<Etudiant>();
            OleDbDataAdapter adapter;

            oleConnexion.Open();
            adapter = new OleDbDataAdapter(commande, oleConnexion);
            
            if (parametres != null)
            {
                foreach (OleDbParameter parametre in parametres)
                {
                    adapter.SelectCommand.Parameters.Add(parametre);
                }
            }

            adapter.Fill(datasetConnexion, "etudiants");

            listeRetour = datasetConnexion.Tables["etudiants"].AsEnumerable().Select(etu => new Etudiant(etu["matricule"].ToString(),etu["nom"].ToString(),
                            etu["prenom"].ToString(),etu["adresse"].ToString(),etu["ville"].ToString(),etu["code"].ToString(),etu["tel"].ToString(),Convert.ToInt32(etu["departement"]))).ToList();


            maConnexion.oleConnexion.Close();
            return listeRetour;
        }


        public List<Resultat> ExecuterAdapterResultat(string commande, List<OleDbParameter> parametres = null)
        {
            Contract.Requires(MaConnexion.OleConnexion != null, "Erreur à l'ouverture de la connexion.");
            Contract.Requires(!String.IsNullOrEmpty(commande), "La commande doit être définie.");
            Contract.Ensures(MaConnexion.OleConnexion.State == ConnectionState.Closed, "La connexion ne c'est pas fermer correctement");
            
            List<Resultat> listeRetour = new List<Resultat>();
            OleDbDataAdapter adapter;

            oleConnexion.Open();
            adapter = new OleDbDataAdapter(commande, oleConnexion);

            if (parametres != null)
            {
                foreach (OleDbParameter parametre in parametres)
                {
                    adapter.SelectCommand.Parameters.Add(parametre);
                }
            }

            adapter.Fill(datasetConnexion, "resultats");

            listeRetour = datasetConnexion.Tables["resultats"].AsEnumerable().Select(res => new Resultat(res["matricule"].ToString(), res["sigle"].ToString(), res["cote"].ToString())).ToList();

            maConnexion.oleConnexion.Close();
            return listeRetour;
        }



        public List<Cours> ExecuterAdapterCours(string commande, List<OleDbParameter> parametres = null)
        {
            Contract.Requires(MaConnexion.OleConnexion != null, "Erreur à l'ouverture de la connexion.");
            Contract.Requires(!String.IsNullOrEmpty(commande), "La commande doit être définie.");
            Contract.Ensures(MaConnexion.OleConnexion.State == ConnectionState.Closed, "La connexion ne c'est pas fermer correctement");
            
            List<Cours> listeRetour = new List<Cours>();
            OleDbDataAdapter adapter;

            oleConnexion.Open();
            adapter = new OleDbDataAdapter(commande, oleConnexion);

            if (parametres != null)
            {
                foreach (OleDbParameter parametre in parametres)
                {
                    adapter.SelectCommand.Parameters.Add(parametre);
                }
            }

            adapter.Fill(datasetConnexion, "cours");

            listeRetour = datasetConnexion.Tables["cours"].AsEnumerable().Select(co => new Cours(co["sigle"].ToString(), co["nom"].ToString(), co["description"].ToString(), Convert.ToDouble(co["credit"]))).ToList();


            maConnexion.oleConnexion.Close();
            return listeRetour;
        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }
    }
    
}
